package com.rg.inf.action;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;

import com.rd.sys.common.utils.client.AnalysisPathUtils;
import com.rd.sys.dto.client.store.Answer;
import com.rd.sys.dto.client.store.Material;
import com.rd.sys.dto.client.store.Project;
import com.rd.sys.dto.client.store.Question;
import com.rd.sys.dto.client.store.QuestionOption;
import com.rd.sys.dto.client.store.Result;
import com.rd.sys.dto.client.store.Scheme;
import com.rd.sys.dto.client.sync.AnswerSyncMsgBody;
import com.rd.sys.dto.client.sync.MaterialSyncMsgBody;
import com.rd.sys.dto.client.sync.MsgBody;
import com.rd.sys.dto.client.sync.ProjectSyncMsgBody;
import com.rd.sys.dto.client.sync.QuestionOptionSyncMsgBody;
import com.rd.sys.dto.client.sync.QuestionSyncMsgBody;
import com.rd.sys.dto.client.sync.ResultSyncMsgBody;
import com.rd.sys.dto.client.sync.SchemeSyncMsgBody;
import com.rd.sys.dto.commmon.base.EyeException;
import com.rd.sys.dto.commmon.base.EyeResult;
import com.rd.sys.dto.sys.user.UserInfoDto;
import com.rd.sys.dto.sys.user.UserSubscriptionDto;
import com.rd.sys.service.sys.user.UserPackageService;
import com.rd.sys.service.sys.user.UserSubscriptionService;
import com.rd.sys.service.sys.user.impl.UserPackageServiceException;
import com.rd.sys.service.sys.user.impl.UserSubscriptionServiceException;

public abstract class BaseExecuteAction {
    protected UserSubscriptionService userSubscriptionService = (UserSubscriptionService) getService("userSubscriptionServiceImpl");
    protected UserPackageService userPackageService = (UserPackageService) getService("userPackageServiceImpl");

    public abstract EyeResult execute(UserInfoDto userInfo, MsgBody msgBody, Object... objs) throws EyeException,
            Exception;

    /**
     * 获取Service层服务实例
     * 
     * @param beanName
     * @return
     */
    protected Object getService(String beanName) {
        WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
        return context.getBean(beanName);
    }

    /**
     * 检查用户目录存在性,不存在则创建目录
     * 
     * @param usercode
     */
    protected void checkUserExist(String userCode) throws Exception {
        String path = AnalysisPathUtils.findUserPath(userCode);
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdir();
        }
    }

    /**
     * 
     * 
     * @param userCode
     * @param projectCode
     * @throws EyeException
     * @throws Exception
     */

    /**
     * 检查项目目录存在性,存在则根据boolean判断是否抛出异常
     * 
     * @param userCode
     * @param projectCode
     * @param throwException
     *            存在是否抛异常
     * @return 目录是否存在, true 存在
     *         <p>
     *         false 不存在
     * @throws EyeException
     * @throws Exception
     */
    protected boolean checkProjectExist(String userCode, String projectCode, boolean throwException)
            throws EyeException, Exception {
        String path = AnalysisPathUtils.findProjectPath(userCode, projectCode);
        File dir = new File(path);
        if (!dir.exists()) {
            return false;
        } else {
            if (throwException) {
                throw new EyeException(EyeResult.ResultDefine.SYNC_PROJECT_EXIST_ERROR);
            }
            return true;
        }
    }

    /**
     * 检查项目目录存在性,若不存在则抛出异常
     * 
     * @param userCode
     * @param projectCode
     * @throws EyeException
     * @throws Exception
     */
    protected void checkProjectNotExist(String userCode, String projectCode) throws EyeException, Exception {
        String path = AnalysisPathUtils.findProjectPath(userCode, projectCode);
        File dir = new File(path);
        if (!dir.exists()) {
            throw new EyeException(EyeResult.ResultDefine.SYNC_PROJECT_NOT_EXIST_ERROR);
        }
    }

    /**
     * 检查方案目录存在性,存在则根据boolean判断是否抛出异常
     * 
     * @param userCode
     * @param projectCode
     * @param schemeCode
     * @param throwException
     *            存在是否抛异常
     * @return 目录是否存在, true 存在
     *         <p>
     *         false 不存在
     * @throws EyeException
     * @throws Exception
     */
    protected boolean checkSchemeExist(String userCode, String projectCode, String schemeCode, boolean throwException)
            throws EyeException, Exception {
        String path = AnalysisPathUtils.findSchemePath(userCode, projectCode, schemeCode);
        File dir = new File(path);
        if (!dir.exists()) {
            return false;
        } else {
            if (throwException) {
                throw new EyeException(EyeResult.ResultDefine.SYNC_SCHEME_EXIST_ERROR);
            }
            return true;
        }
    }

    /**
     * 检查方案目录存在性,若不存则抛出异常
     * 
     * @param userCode
     * @param projectCode
     * @param schemeCode
     * @throws EyeException
     * @throws Exception
     */
    protected void checkSchemeNotExist(String userCode, String projectCode, String schemeCode) throws EyeException,
            Exception {
        String path = AnalysisPathUtils.findSchemePath(userCode, projectCode, schemeCode);
        File dir = new File(path);
        if (!dir.exists()) {
            throw new EyeException(EyeResult.ResultDefine.SYNC_SCHEME_NOT_EXIST_ERROR);
        }
    }

    /**
     * 检查结果目录存在性,存在则根据boolean判断是否抛出异常
     * 
     * @param userCode
     * @param projectCode
     * @param schemeCode
     * @param resultCode
     * @param throwException
     *            存在是否抛异常
     * @return 目录是否存在, true 存在
     *         <p>
     *         false 不存在
     * @throws EyeException
     * @throws Exception
     */
    protected boolean checkResultExist(String userCode, String projectCode, String schemeCode, String resultCode,
            boolean throwException) throws EyeException, Exception {
        String path = AnalysisPathUtils.findResultDataPath(userCode, projectCode, schemeCode, resultCode);
        File dir = new File(path);
        if (!dir.exists()) {
            return false;
        } else {
            if (throwException) {
                throw new EyeException(EyeResult.ResultDefine.SYNC_RESULT_EXIST_ERROR);
            }
            return true;
        }
    }

    /**
     * 检查结果目录存在性,不存在则创建,存在则抛出异常
     * 
     * @param userCode
     * @param projectCode
     * @param schemeCode
     * @param resultCode
     * @throws EyeException
     * @throws Exception
     */
    protected void checkResultNotExist(String userCode, String projectCode, String schemeCode, String resultCode)
            throws EyeException, Exception {
        String path = AnalysisPathUtils.findResultDataPath(userCode, projectCode, schemeCode, resultCode);
        File dir = new File(path);
        if (!dir.exists()) {
            throw new EyeException(EyeResult.ResultDefine.SYNC_RESULT_NOT_EXIST_ERROR);
        }
    }

    /**
     * 检查用户订购关系
     * 
     * @param userno
     * @return
     * @throws EyeException
     * @throws Exception
     */
    protected UserSubscriptionDto checkSubscription(Integer userno) throws EyeException, Exception {
        UserSubscriptionDto sub = new UserSubscriptionDto();
        sub.setUserno(userno);
        try {
            // 专业版不再检查订购关系
            // sub = userSubscriptionService.checkSubscription(sub);
        } catch (UserSubscriptionServiceException ex) {
            if (ex.getErroCode() == UserSubscriptionServiceException.SUBSCRIPTION_NOT_USER) {
                // 不存在
                throw new EyeException(EyeResult.ResultDefine.SYNC_SUBSCRIPTION_NOT_USER_ERROR);
            } else if (ex.getErroCode() == UserSubscriptionServiceException.SUBSCRIPTION_OVERDUE) {
                // 已过期
                throw new EyeException(EyeResult.ResultDefine.SYNC_SUBSCRIPTION_OVERDUE_ERROR);
            } else if (ex.getErroCode() == UserSubscriptionServiceException.SUBSCRIPTION_NOT_NORMAL) {
                // 非正常状态
                throw new EyeException(EyeResult.ResultDefine.SYNC_SUBSCRIPTION_NOT_NORMAL_ERROR);
            } else {
                throw ex;
            }
        }
        return sub;
    }

    /**
     * 检查用户套餐使用情况
     * 
     * @param sub
     *            订购关系
     * @param isCheckProject
     *            是否检查项目使用情况
     * @param isCheckScheme
     *            是否检查方案使用情况
     * @param isCheckResult
     *            是否检查结果使用情况
     * @throws Exception
     */
    protected void checkPackage(UserSubscriptionDto sub, boolean isCheckProject, boolean isCheckScheme,
            boolean isCheckResult) throws EyeException, Exception {
        try {
            // 专业版不再检查订购关系
            // userPackageService.checkPackageUsage(sub, isCheckProject,
            // isCheckScheme, isCheckResult);
        } catch (UserPackageServiceException ex) {
            if (ex.getErroCode() == UserPackageServiceException.SUBSCRIPTION_MAX_PROJECT) {
                // 项目达到限制
                throw new EyeException(EyeResult.ResultDefine.SYNC_SUBSCRIPTION_MAX_PROJECT_ERROR);
            } else if (ex.getErroCode() == UserPackageServiceException.SUBSCRIPTION_MAX_SCHEME) {
                // 方案达到限制
                throw new EyeException(EyeResult.ResultDefine.SYNC_SUBSCRIPTION_MAX_SCHEME_ERROR);
            } else if (ex.getErroCode() == UserPackageServiceException.SUBSCRIPTION_MAX_RESULT) {
                // 结果达到限制
                throw new EyeException(EyeResult.ResultDefine.SYNC_SUBSCRIPTION_MAX_RESULT_ERROR);
            } else {
                throw ex;
            }
        }
    }

    /**
     * 项目对象转换. 将接口消息对象转换为存储对象
     * 
     * @param msgBody
     * @return
     * @throws Exception
     */
    protected Project transProject(ProjectSyncMsgBody msgBody) throws Exception {
        Project project = new Project();
        BeanUtils.copyProperties(project, msgBody);
        return project;
    }

    /**
     * 方案对象转换. 将接口消息对象转换为存储对象
     * 
     * @param msgBody
     * @return
     * @throws Exception
     */
    protected Scheme transScheme(SchemeSyncMsgBody msgBody) throws Exception {
        /** 复制基本属性 */
        Scheme scheme = new Scheme();
        BeanUtils.copyProperties(scheme, msgBody);

        /** 复制素材List属性 */
        List<Material> materials = null;
        if (msgBody.getMaterials() != null) {
            materials = new LinkedList<Material>();
            Iterator<MaterialSyncMsgBody> iterator = msgBody.getMaterials().iterator();
            Material material = null;
            while (iterator.hasNext()) {
                material = new Material();
                BeanUtils.copyProperties(material, iterator.next());
                materials.add(material);
            }
        }
        scheme.setMaterials(materials);

        /** 复制问卷List属性 */
        List<Question> questions = null; // 问卷
        if (msgBody.getQuestions() != null) {
            questions = new LinkedList<Question>();
            Iterator<QuestionSyncMsgBody> iterator = msgBody.getQuestions().iterator();
            Question question = null;
            QuestionSyncMsgBody questionSync = null;
            while (iterator.hasNext()) {
                question = new Question();
                questionSync = iterator.next();
                BeanUtils.copyProperties(question, questionSync);

                /** 问卷中包含有选项,也需要单独复制 */
                List<QuestionOption> optionList = null;
                if (questionSync.getOptionList() != null) {
                    optionList = new LinkedList<QuestionOption>();
                    Iterator<QuestionOptionSyncMsgBody> iterator_optionList = questionSync.getOptionList().iterator();
                    QuestionOption option = null;
                    while (iterator_optionList.hasNext()) {
                        option = new QuestionOption();
                        BeanUtils.copyProperties(option, iterator_optionList.next());
                        optionList.add(option);
                    }
                }
                question.setOptionList(optionList);

                questions.add(question);
            }
        }
        scheme.setQuestions(questions);

        return scheme;
    }

    /**
     * 结果对象转换. 将接口消息对象转换为存储对象
     * 
     * @param msgBody
     * @return
     * @throws Exception
     */
    protected Result transResult(ResultSyncMsgBody msgBody) throws Exception {
        /** 复制基本属性 */
        Result result = new Result();
        BeanUtils.copyProperties(result, msgBody);

        /** 复制问卷答案List属性 */
        List<Answer> answers = null;
        if (msgBody.getAnswers() != null) {
            answers = new LinkedList<Answer>();
            Iterator<AnswerSyncMsgBody> iterator = msgBody.getAnswers().iterator();
            Answer answer = null;
            while (iterator.hasNext()) {
                answer = new Answer();
                BeanUtils.copyProperties(answer, iterator.next());
                answers.add(answer);
            }
        }
        result.setAnswers(answers);

        return result;
    }
}
